package com.documents.common.core.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
@SuppressWarnings("all")
public abstract class BaseDao<T, ID extends Serializable> extends HibernateDaoSupport {
	protected Class<T> entityClass;//实体类型
	protected String tableName;//表名
	protected JdbcTemplate jdbcTemplate;
	
	protected static final String SELECT = " select ";
	protected static final String FROM = " from ";
	protected static final String WHERE = " where ";
	protected static final String AND = " and ";
	protected static final String OR = " or ";
	protected static final String ORDERBY = " order by ";
	
	protected static final String COUNT(String item) {
		if(item == null || item.length() == 0)
			item = "*";
		return " count(" + item + ")";
	}
	
	protected Class<T> getEntityClass() {
		//获取父类第一个泛型参数的Class
		ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
		entityClass = (Class<T>) type.getActualTypeArguments()[0];
		return entityClass;
	}

	protected void setEntityClass(Class<T> entityClass) {
		this.entityClass = entityClass;
	}

	protected String getTableName() {
		return tableName;
	}

	protected void setTableName(String tableName) {
		this.tableName = tableName;
	}

	protected JdbcTemplate getJdbcTemplate() {
		return jdbcTemplate;
	}

	protected void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}

	public void delById(ID id) {
		getHibernateTemplate().delete(getHibernateTemplate().get(getEntityClass(), id));
	}

	public void delete(T obj) {
		getHibernateTemplate().delete(obj);
	}

	public boolean exists(String condition, Object[] parameters) {
		if(this.findTotalCount(condition, parameters)==0){
			return false;
		}else{
			return true;
		}
	}

	public List<T> find(String condition, Object[] parameters, String sort) {
		String hql = FROM + getEntityClass().getName();
		if(condition!=null&&!condition.equals("")){
			hql += WHERE +condition;
		}
		if (sort != null && !sort.equals("")) {
			String tmpHql = hql.toLowerCase();
			if (tmpHql.indexOf(ORDERBY) < 0)
				hql = (hql + ORDERBY + sort);
		}
		return getHibernateTemplate().find(hql, parameters);
	}

	public long findTotalCount(final String condition, final Object[] parameters) {
		Object obj = getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session s)
					throws HibernateException, SQLException {
				String hql = SELECT + COUNT("*") + FROM  + getEntityClass().getName();
				if(condition!=null&&!condition.equals("")){
					hql += WHERE + condition;
				}
				Query query = createQuery(s, hql, parameters);
                            
				return query.uniqueResult();
			}
		});
		if(obj==null){
			return 0;
		}else{
			return (Long)obj;
		}
	}

	public T findUnique(final String condition, final Object[] parameters) {
		Object obj = getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session s)
					throws HibernateException, SQLException {
				String hql = FROM + getEntityClass().getName();
				if(condition!=null&&!condition.equals("")){
					hql += WHERE + condition;
				}
				Query query = createQuery(s, hql, parameters);
				query.setFirstResult(0);
				query.setMaxResults(1);
				List list = query.list();
				if(list!=null&&!list.isEmpty()){
					return list.get(0);
				}else{
					return null;
				}
			}
		});
		return (T)obj;
	}

	public List<T> findWithPaging(final String condition, final Object[] parameters, final String sort,
			final int start, final int limit) {
		Object obj = getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session s)
					throws HibernateException, SQLException {
				String hql = FROM + getEntityClass().getName();
				if(condition!=null&&!condition.equals("")){
					hql += WHERE + condition;
				}
				if (sort != null && !sort.equals("")) {
					String tmpHql = hql.toLowerCase();
					if (tmpHql.indexOf(ORDERBY) < 0)
						hql = (hql + ORDERBY + sort);
				}
				Query query = createQuery(s, hql, parameters);
				query.setFirstResult(start);
				query.setMaxResults(limit);
				return query.list();
			}
		});
		return (List<T>)obj;
	}

	public T get(ID id) {
		return (T)getHibernateTemplate().get(getEntityClass(), id);
	}

	public T load(ID id) {
		return (T)getHibernateTemplate().load(getEntityClass(), id);
	}

	public void save(T obj) {
          obj = (T)getHibernateTemplate().merge(obj);
	  getHibernateTemplate().save(obj);
	}

	public void update(T obj) {
            if(obj!=null)
            {
              obj = (T)getHibernateTemplate().merge(obj);
            }
		getHibernateTemplate().update(obj);
	}
	
	public Query createQuery(Session session, String hql, Object[] parameters) {
		Query query = session.createQuery(hql);
		if (parameters != null) {
			for (int i = 0; i < parameters.length;i++) {
				if(parameters[i]!=null){
					query.setParameter(i, parameters[i]);
				}
			}
		}
		return query;
	}

	public List<T> findAll() {
		return this.find(null, null, null);
	}

	public void bulkDelByIds(final ID[] ids) {
		final String queryString = "delete "+getEntityClass().getName()+" where id in (:ids) ";
        getHibernateTemplate().execute(new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                Query query = session.createQuery(queryString);
                query.setParameterList("ids", ids);
                return query.executeUpdate();
            }
        });
		
	}
}
